package org.atlantis.nio;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * 各种IO写入性能的测试。测试方式：每次写入10个字节的内容，写入100万次。
 * 
 * @author <a href="mailto:seenoevil.cn@gmail.com">李曦</a><br/>
 *         $Created at: 2012-2-23 下午7:29:59
 */
public class PerfBenchmark {

	private static final File TEST_FILE = new File("F:/perf_test");
	private static final byte[] PER_CONTENT = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
			(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j' };
	private static final int WRITE_COUNT = 1000000;
	private static final int AVG_COUNT = 3;

	public static void main(String[] args) throws Exception {
		long startTime = System.currentTimeMillis();
		for (int i = 0; i < AVG_COUNT; i++) {
			testFileChannel();
		}
		long endTime = System.currentTimeMillis();
		System.out.println("Waste Time: " + (endTime - startTime) / AVG_COUNT + " ms.");
	}

	// 测试FileOutputStream的写入速度：5766ms
	static void testFileOutputStream() throws Exception {
		OutputStream out = new FileOutputStream(TEST_FILE);
		for (int i = 0; i < WRITE_COUNT; i++) {
			out.write(PER_CONTENT);
		}
		out.flush();
		out.close();
	}

	// 测试BufferedOutputStream的写入速度：100ms
	static void testBufferedFileOutputStream() throws Exception {
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(TEST_FILE), 1024 * 64);
		for (int i = 0; i < WRITE_COUNT; i++) {
			out.write(PER_CONTENT);
		}
		out.flush();
		out.close();
	}

	// 测试RandomAccessFile的写入速度：5646ms
	static void testRandomAccessFile() throws Exception {
		RandomAccessFile out = new RandomAccessFile(TEST_FILE, "rw");
		for (int i = 0; i < WRITE_COUNT; i++) {
			out.write(PER_CONTENT);
		}
		out.close();
	}

	// 测试MappedByteBuffer的写入速度：453ms
	static void testMappedByteBuffer() throws Exception {
		MappedByteBuffer out = new RandomAccessFile(TEST_FILE, "rw").getChannel().map(MapMode.READ_WRITE, 0,
				PER_CONTENT.length * WRITE_COUNT);
		for (int i = 0; i < WRITE_COUNT; i++) {
			out.put(PER_CONTENT);
		}
		out.force();
	}

	// 测试testFileChannel的写入速度：6531ms（可以使用Gather优化）
	static void testFileChannel() throws Exception {
		FileChannel out = new FileOutputStream(TEST_FILE).getChannel();
		ByteBuffer buf = ByteBuffer.allocateDirect(10);
		buf.put(PER_CONTENT);
		for (int i = 0; i < WRITE_COUNT; i++) {
			out.write(buf);
			buf.rewind();
		}
		out.force(false);
		out.close();
	}
}
